#!/usr/bin/perl
use strict;
use warnings;
use CGI ();

#use CGI::Carp qw(fatalsToBrowser);
use MIME::Lite ();
use Contact;
use Storable qw(lock_store);
use Mail::CheckUser qw(check_email last_check);

$Mail::CheckUser::Timeout               = 10;
$Mail::CheckUser::Treat_Timeout_As_Fail = undef;

my $sender_email          = "\"OCF Convention 2009\" <committee\@ocfconvention.org>";
my $error_email           = "\"Woei Shyang\" <woei\@dino.ocfaustralia.org>";
my $debug_email           = "\"Woei Shyang\" <woei\@dino.ocfaustralia.org>";
my @contact_fields        = ( 'name', 'family_name', 'email', 'mobile', 'country' );
my @unique_contact_fields = ( 'email', 'mobile' );
my $cgi                   = new CGI;
my $rv;

if ( $ENV{REQUEST_METHOD} =~ /^GET$/ ) {
    print $cgi->header();
    print $cgi->start_html( { 'title' => 'Unsubscribe' } );
    print $cgi->h3('Stop receiving emails');
    print $cgi->start_form( { 'method' => 'POST' } );

    print $cgi->textfield( { 'name' => 'deactivate_email', 'size' => 50, 'maxlength' => 128 } );
    print $cgi->submit( { 'name' => 'deactivate', 'value' => 'Unsubscribe Email' } );
    print $cgi->endform;
    print $cgi->end_html();

} ## end if ( $ENV{REQUEST_METHOD} =~ /^GET$/ )
else {

    if ( $cgi->param('deactivate_email') ) {
        my $c = Contact->new( 'email' => $cgi->param('deactivate_email') );
        my $rv;
        $rv = $c->load( 'speculative' => 1 );

        if ($rv) {
            $c->active(0);
            $c->save();
            print $cgi->header();
            print $cgi->start_html( -title => $cgi->param('deactivate_email') . ' unsubscribed' );
            print $cgi->end_html();
        } ## end if ($rv)
        else {
            print $cgi->header();
            print $cgi->start_html( -title => 'Unsubscribe' );
            print $cgi->end_html();
        }

    } ## end if ( $cgi->param('deactivate_email') )

    else {
        my $contactData = {};

        foreach my $contact_field (@contact_fields) {
            $contactData->{$contact_field} = $cgi->param($contact_field) if ( $cgi->param($contact_field) );
        }
        eval { $rv = insertOrUpdateContact($contactData); };
        if ($@) {

            # fire an email off to have someone look at it
            sendErrorEmail( { 'error' => $@, 'cgi' => $cgi } );

            # meanwhile display a informative page for the user
            print $cgi->header();
            print $cgi->start_html( -title => 'Guru Meditation' );
            print $cgi->p(
                "Sorry, a software error has been encountered. A notification has been generated for this issue to be attended to, please try again later."
            );
            print $cgi->hr();
            print $cgi->p(
                { 'align' => 'left' },
                "If you require further technical assistance please contact <a href=\"mailto:woei\@dino.ocfaustralia.org\"><i>woei\@dino.ocfaustralia.org</i></a>"
            );
            print $cgi->end_html();

            # end the script
            exit;
        } ## end if ($@)
        if ( $rv->{'errors'} && scalar( @{ $rv->{'errors'} } ) ) {
            sendDebugEmail();
            print $cgi->header();
            print $cgi->start_html("Error encountered signing up");
            print $cgi->h1("Incomplete details provided");
            foreach my $error ( @{ $rv->{'errors'} } ) {
                print $cgi->p($error);
            }
            print $cgi->hr();
            print $cgi->p(
                { 'align' => 'left' },
                "If you require further technical assistance please contact <a href=\"mailto:woei\@dino.ocfaustralia.org\"><i>woei\@dino.ocfaustralia.org</i></a>"
            );
            print $cgi->end_html();
        } ## end if ( $rv->{'errors'} && scalar( @{ $rv->{'errors'...
        else {
            sendConfirmationEmail( { 'name' => $cgi->param('name'), 'email' => $cgi->param('email') } );
            print $cgi->header();
            print $cgi->start_html(
                -title => 'Thank you',
                -head  => $cgi->meta( { -http_equiv => 'REFRESH', -content => '1;url=http://ocfconvention.org' } )
            );
            print $cgi->h1("You have been subscribed to the list");
            print $cgi->end_html();
        } ## end else [ if ( $rv->{'errors'} && scalar( @{ $rv->{'errors'...
    } ## end else [ if ( $cgi->param('deactivate_email') )

} ## end else [ if ( $ENV{REQUEST_METHOD} =~ /^GET$/ )

sub validateContact {
    my $params = shift;
    my @errors;

    $params->{'mobile'} =~ s/\s*//g;

    if ( !defined( $params->{'name'} ) || !$params->{'name'} ) {
        push @errors, "Name is not specified";
    }
    if ( !defined( $params->{'family_name'} ) || !$params->{'family_name'} ) {
        push @errors, "Family name is not specified";
    }
    if ( !defined( $params->{'email'} ) || !$params->{'email'} ) {
        push @errors, "Email address is not specified";
    }
    elsif ( $params->{'email'} && !check_email( $params->{'email'} ) ) {
        push @errors,
            "Please use a different email address, " . $params->{'email'} . " isn't valid: " . last_check()->{reason};
    }
    if ( !defined( $params->{'mobile'} ) || !$params->{'mobile'} ) {
        push @errors, "Mobile number is not specified";
    }
    elsif ( $params->{'mobile'} !~ /\d{7}/ ) {
        push @errors, "Invalid mobile number is specified";
    }
    if ( !defined( $params->{'country'} ) || !$params->{'country'} ) {
        push @errors, "Home country is not specified";
    }
    return @errors;
} ## end sub validateContact

sub insertOrUpdateContact {
    my $params = shift;
    my @errors;
    $params->{'mobile'} =~ s/[^\d]//g;
    my @validation_errors = validateContact($params);
    if ( !scalar(@validation_errors) ) {
        my $c = Contact->new();

        # check to see if existing contacts are present
        foreach my $unique_field (@unique_contact_fields) {
            $c = Contact->new( $unique_field => $params->{$unique_field} );
            my $rv;
            $rv = $c->load( 'speculative' => 1 );
            if ($rv) {
                last;
            }
        } ## end foreach my $unique_field (@unique_contact_fields)
        foreach my $field_name ( keys(%$params) ) {
            $c->$field_name( $params->{$field_name} );
        }
        $c->modified(undef);
        $c->active(1);
        $c->save();
    } ## end if ( !scalar(@validation_errors) )
    else {
        push @errors, @validation_errors;
    }
    return { 'errors' => \@errors };
} ## end sub insertOrUpdateContact

sub sendErrorEmail {
    my $params = shift              || {};
    my $error  = $params->{'error'} || '';
    my $cgi    = $params->{'cgi'}   || new CGI;
    my $msg    = new MIME::Lite(
        From    => $sender_email,
        To      => $error_email,
        Subject => "Software error",
        Type    => "multipart/mixed",
        Data    => '',
    );
    if ($error) {
        $msg->attach( Type => "TEXT", Data => "$error" );
    }
    if ($cgi) {
        my $dump_file = time . ".dump";
        lock_store( $cgi, $dump_file );
        $msg->attach( Type => "binary/octet-stream", Filename => $dump_file, );
    }
    $msg->send();
} ## end sub sendErrorEmail

sub sendConfirmationEmail {
    my $params = shift              || {};
    my $name   = $params->{'name'}  || '';
    my $email  = $params->{'email'} || '';
    my $bodytext = "Hi $name,

Thank you for signing up to receive updates with regards to the upcoming OCF Convention in Melaka from 9 - 13 Dec 2009. We hope to update you with the latest pictures, videos and information on the production of the entire convention to its registration.

Kind regards,
Kenneth Kwan
(Convention Committee Member)

PS: If you'd like to unsubscribe from this mailing list at any point, please send a blank email to unsubscribe\@ocfconvention.org";
    my $msg = new MIME::Lite(
        From    => $sender_email,
        To      => "\"$name\" <$email>",
        Subject => "Subscription confirmation",
        Type    => "TEXT",
        Data    => $bodytext,
    );
    $msg->send();
} ## end sub sendConfirmationEmail

sub sendDebugEmail {
    my $cgi      = new CGI;
    my $bodytext = "";

    foreach my $envkey ( keys(%ENV) ) {
        $bodytext .= $envkey . "=" . $ENV{$envkey} . "\n";
    }
    $bodytext .= "---\n\n";
    foreach my $key (@contact_fields) {
        $bodytext .= $key . "=" . $cgi->param($key) . "\n";
    }

    my $msg = new MIME::Lite(
        From    => $debug_email,
        To      => $debug_email,
        Subject => "[DEBUG] Convention updates signup",
        Type    => "TEXT",
        Data    => $bodytext,
    );
    $msg->send();
} ## end sub sendDebugEmail

